/**
 ******************************************************************************
 * @file    can.c
 * @author  GEEKROS,  site:www.geekros.com
 ******************************************************************************
 */

#include "can.h"

Can_Struct Can_Data;

Can_Current_Struct Can_Current_Data[CAN_MOTOR_LEN];

/*******************************************************************************
 * @funtion      : Can_Init
 * @description  : 模块初始化，依次初始化Can1_Init
 * @param         {*}
 * @return        {*}
 *******************************************************************************/
void Can_Init(void)
{
    Can1_Init();
}

/*******************************************************************************
 * @funtion      : Can1_Init
 * @description  : CAN1初始化，开发板共10组CAN1接口
 * @param         {*}
 * @return        {*}
 *******************************************************************************/
void Can1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    CAN_InitTypeDef CAN_InitStructure;
    CAN_FilterInitTypeDef CAN_FilterInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

    GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    CAN_DeInit(CAN1);

    CAN_InitStructure.CAN_TTCM = DISABLE;
    CAN_InitStructure.CAN_ABOM = DISABLE;
    CAN_InitStructure.CAN_AWUM = DISABLE;
    CAN_InitStructure.CAN_NART = DISABLE;
    CAN_InitStructure.CAN_RFLM = DISABLE;
    CAN_InitStructure.CAN_TXFP = DISABLE;
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
    CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;

    CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
    CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq;
    CAN_InitStructure.CAN_Prescaler = 3;
    CAN_Init(CAN1, &CAN_InitStructure);

    CAN_FilterInitStructure.CAN_FilterNumber = 0;
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
    CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);

    CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
    CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE);
}

/*******************************************************************************
 * @funtion      : CAN1_RX0_IRQHandler
 * @description  : CAN1中断回调函数
 * @param         {*}
 * @return        {*}
 *******************************************************************************/
void CAN1_RX0_IRQHandler(void)
{
    if (CAN_GetITStatus(CAN1, CAN_IT_FMP0) != RESET)
    {
        CanRxMsg That_Data;
        CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
        CAN_Receive(CAN1, CAN_FIFO0, &That_Data);
            
        // 将CAN数据进行统一处理
        Can1_Data_Callback(That_Data);
    }
}

/*******************************************************************************
 * @funtion      : Can1_Data_Callback
 * @description  : CAN1中断回调函数
 * @param         {*}
 * @return        {*}
 *******************************************************************************/
void Can1_Data_Callback(CanRxMsg can_read_data)
{
    switch(can_read_data.StdId)
    {
        case 0x201:
            Can_Current_Data[0].Single_Position = can_read_data.Data[0];
            Can_Current_Data[0].Single_Position <<=8;
            Can_Current_Data[0].Single_Position |= can_read_data.Data[1];
            Can_Current_Data[0].Position = can_read_data.Data[2];
            Can_Current_Data[0].Position <<=8;
            Can_Current_Data[0].Position |= can_read_data.Data[3];
            Can_Current_Data[0].Speed = can_read_data.Data[4];
            Can_Current_Data[0].Speed <<=8;
            Can_Current_Data[0].Speed |= can_read_data.Data[5];
            Can_Current_Data[0].Current = can_read_data.Data[6];
            Can_Current_Data[0].Current <<=8;
            Can_Current_Data[0].Current |= can_read_data.Data[7];
        break;
        case 0x202:
            Can_Current_Data[1].Single_Position = can_read_data.Data[0];
            Can_Current_Data[1].Single_Position <<=8;
            Can_Current_Data[1].Single_Position |= can_read_data.Data[1];
            Can_Current_Data[1].Position = can_read_data.Data[2];
            Can_Current_Data[1].Position <<=8;
            Can_Current_Data[1].Position |= can_read_data.Data[3];
            Can_Current_Data[1].Speed = can_read_data.Data[4];
            Can_Current_Data[1].Speed <<=8;
            Can_Current_Data[1].Speed |= can_read_data.Data[5];
            Can_Current_Data[1].Current = can_read_data.Data[6];
            Can_Current_Data[1].Current <<=8;
            Can_Current_Data[1].Current |= can_read_data.Data[7];
        break;
        case 0x203:
            Can_Current_Data[2].Single_Position = can_read_data.Data[0];
            Can_Current_Data[2].Single_Position <<=8;
            Can_Current_Data[2].Single_Position |= can_read_data.Data[1];
            Can_Current_Data[2].Position = can_read_data.Data[2];
            Can_Current_Data[2].Position <<=8;
            Can_Current_Data[2].Position |= can_read_data.Data[3];
            Can_Current_Data[2].Speed = can_read_data.Data[4];
            Can_Current_Data[2].Speed <<=8;
            Can_Current_Data[2].Speed |= can_read_data.Data[5];
            Can_Current_Data[2].Current = can_read_data.Data[6];
            Can_Current_Data[2].Current <<=8;
            Can_Current_Data[2].Current |= can_read_data.Data[7];
        break;
        case 0x204:
            Can_Current_Data[3].Single_Position = can_read_data.Data[0];
            Can_Current_Data[3].Single_Position <<=8;
            Can_Current_Data[3].Single_Position |= can_read_data.Data[1];
            Can_Current_Data[3].Position = can_read_data.Data[2];
            Can_Current_Data[3].Position <<=8;
            Can_Current_Data[3].Position |= can_read_data.Data[3];
            Can_Current_Data[3].Speed = can_read_data.Data[4];
            Can_Current_Data[3].Speed <<=8;
            Can_Current_Data[3].Speed |= can_read_data.Data[5];
            Can_Current_Data[3].Current = can_read_data.Data[6];
            Can_Current_Data[3].Current <<=8;
            Can_Current_Data[3].Current |= can_read_data.Data[7];
        case 0x205:
            Can_Current_Data[4].Single_Position = can_read_data.Data[0];
            Can_Current_Data[4].Single_Position <<=8;
            Can_Current_Data[4].Single_Position |= can_read_data.Data[1];
            Can_Current_Data[4].Position = can_read_data.Data[2];
            Can_Current_Data[4].Position <<=8;
            Can_Current_Data[4].Position |= can_read_data.Data[3];
            Can_Current_Data[4].Speed = can_read_data.Data[4];
            Can_Current_Data[4].Speed <<=8;
            Can_Current_Data[4].Speed |= can_read_data.Data[5];
            Can_Current_Data[4].Current = can_read_data.Data[6];
            Can_Current_Data[4].Current <<=8;
            Can_Current_Data[4].Current |= can_read_data.Data[7];
        break;
        case 0x206:
            Can_Current_Data[5].Single_Position = can_read_data.Data[0];
            Can_Current_Data[5].Single_Position <<=8;
            Can_Current_Data[5].Single_Position |= can_read_data.Data[1];
            Can_Current_Data[5].Position = can_read_data.Data[2];
            Can_Current_Data[5].Position <<=8;
            Can_Current_Data[5].Position |= can_read_data.Data[3];
            Can_Current_Data[5].Speed = can_read_data.Data[4];
            Can_Current_Data[5].Speed <<=8;
            Can_Current_Data[5].Speed |= can_read_data.Data[5];
            Can_Current_Data[5].Current = can_read_data.Data[6];
            Can_Current_Data[5].Current <<=8;
            Can_Current_Data[5].Current |= can_read_data.Data[7];
        break;
        
    }
}

/*******************************************************************************
 * @funtion      : Can_Send
 * @description  : 发送电机数据
 * @param         {*}
 * @return        {*}
 *******************************************************************************/
void Can_Send(int StdId, int16_t Data1, int16_t Data2, int16_t Data3, int16_t Data4)
{
	CanTxMsg CanTxData;
    CanTxData.RTR = CAN_RTR_DATA;
    CanTxData.IDE = CAN_ID_STD;
    CanTxData.DLC = 0x08;
    CanTxData.StdId = StdId;
    CanTxData.Data[0] = ((Data1 >> 8) & 0xff);
    CanTxData.Data[1] = (Data1 & 0xff);
    CanTxData.Data[2] = ((Data2 >> 8) & 0xff);
    CanTxData.Data[3] = (Data2 & 0xff);
    CanTxData.Data[4] = ((Data3 >> 8) & 0xff);
    CanTxData.Data[5] = (Data3 & 0xff);
    CanTxData.Data[6] = ((Data4 >> 8) & 0xff);
    CanTxData.Data[7] = (Data4 & 0xff);
    CAN_Transmit(CAN1, &CanTxData);
}

/*******************************************************************************
 * @funtion      : Can_Task
 * @description  : 任务回调函数
 * @param         {*}
 * @return        {*}
 *******************************************************************************/
void Can_Task(void)
{
    
}

/*******************************************************************************
 * @funtion      : Can_Usb_Callback
 * @description  : 串口任务回调函数
 * @param         {char *type} 通讯协议类型
 * @param         {int channel} 通道 可选值1、2
 * @param         {int motor_id} 电机ID
 * @return        {*}
 *******************************************************************************/
void Can_Usb_Callback(char *type, int channel, int motor_id)
{
    if (memcmp(type, "can-read-pid", 12) == 0)
    {
        
    }
}
